/********************************************************************
	TABAL ENGINE - 2012/10/28
	author:		Marc Cuscullola
	
	purpose:	Defines a 2d vector
*********************************************************************/
#pragma once

#ifndef __MATH_VECTOR__VECTOR2__INCLUDED_H__
#define __MATH_VECTOR__VECTOR2__INCLUDED_H__

#include "MathTypes.h"
#include "Angles\MathAngles.h"

template<typename T>
class Vector2
{
public:
	T x, y;

public:
	// Constructor
	inline Vector2 ();
	inline Vector2 (const Vector2<T>& otro);
	inline Vector2 (const T fx, const T fy);
	inline Vector2 (const T escalar);


	// Arithmetic operators
	inline        Vector2<T>  operator + (const Vector2<T>& otro) const;
	inline        Vector2<T>  operator - (const Vector2<T>& otro) const;
	inline        Vector2<T>  operator * (const T escalar) const;
	inline        Vector2<T>  operator / (const T escalar) const;
	inline        Vector2<T>  operator + (const T escalar) const;
	inline        Vector2<T>  operator - (const T escalar) const;
	inline        Vector2<T>  operator - () const;
	inline        Vector2<T>& operator + ();
	inline const  Vector2<T>& operator + () const;


	// Arithmetic update operators
	inline Vector2<T>& operator += (const Vector2<T>& otro);
	inline Vector2<T>& operator -= (const Vector2<T>& otro);
	inline Vector2<T>& operator *= (const T escalar);
	inline Vector2<T>& operator /= (const T escalar);
	inline Vector2<T>& operator += (const T escalar);
	inline Vector2<T>& operator -= (const T escalar);

	// Operators and asignations functions
	inline Vector2<T>& operator ()  (const T tx, const T ty);
	inline void        Set          (const T tx, const T ty);
	inline void        SetZero      ();


	// Polar coordinates
	void  SetFromPolar (const T ang, const T length);
	void  GetPolar     (T& ang, T& length) const;


	// Scalar product (*)
	inline T operator * (const Vector2<T>& otro) const;

	// Operators and comparison functions
	inline bool operator ==       (const Vector2<T>& otro) const;
	inline bool operator !=       (const Vector2<T>& otro) const;
	inline bool IsEqualEpsilon    (const Vector2<T>& otro) const;
	inline bool IsNotEqualEpsilon (const Vector2<T>& otro) const;

	// Product by components
	inline Vector2<T>& Scale     (const Vector2<T>& otro);
	inline Vector2<T>  GetScaled (const Vector2<T>& otro) const;

	// Condicional establishment
	inline const Vector2<T>& SetIfMinComponents (const Vector2<T>& otro);
	inline const Vector2<T>& SetIfMaxComponents (const Vector2<T>& otro);


	// Access operators []
	inline T  operator [] (int i) const;
	inline T& operator [] (int i);


	// Longitude functions
	inline Vector2<T>&	Normalize		(const T tk = One<T>());
	inline Vector2<T>	GetNormalized	() const;
	inline T			Length			() const;
	inline T			SquaredLength	() const;
	inline T			Distance		(const Vector2<T>& rhs) const;
	inline T			SqDistance		(const Vector2<T>& rhs) const;

	inline float		Dot				(const Vector2<T>& otro) const;

	// Rotations
	inline Vector2<T>&	Rotate			(const T angle);
	inline Vector2<T>	GetRotated		(const T angle) const;
	inline T			GetAngle		() const;
	inline Vector2<T>	GetXYFromAngle	(float radians);
	inline Vector2<T>&  GetPerpendicular();

	// Linear interpolation
	inline Vector2<T>&	Lerp    (const Vector2<T>& otro, const T t);
	inline Vector2<T>	GetLerp (const Vector2<T>& otro, const T t) const;
};

//--------------------------------------------------------------------------
// OPERADORES EXTERNOS
//--------------------------------------------------------------------------
// Operadores para poder usar orden inverso en las expresiones
template<typename T> inline Vector2<T>  operator * (const T escalar, const Vector2<T>& otro);
template<typename T> inline Vector2<T>  operator / (const T escalar, const Vector2<T>& otro);
template<typename T> inline Vector2<T>  operator + (const T escalar, const Vector2<T>& otro);
template<typename T> inline Vector2<T>  operator - (const T escalar, const Vector2<T>& otro);

//--------------------------------------------------------------------------
// FUNCIONES EXTERNAS
//--------------------------------------------------------------------------
template<typename T> inline Vector2<T> VectorMinComponents (const Vector2<T>& uno, const Vector2<T>& otro);
template<typename T> inline Vector2<T> VectorMaxComponents (const Vector2<T>& uno, const Vector2<T>& otro);

/************************************************************************/
/* Definitions file		                                                */
/************************************************************************/
#include "Vector2.inl"

//--------------------------------------------------------------------------
// TIPOS DE VECTORES 2D CON TIPOS CONCRETOS DE DATOS
//--------------------------------------------------------------------------
typedef Vector2<float>  Vect2f;
typedef Vector2<double> Vect2d;
typedef Vector2<int32>  Vect2i;
typedef Vector2<uint32> Vect2u;
typedef Vector2<uint16> Vect2w;

//--------------------------------------------------------------------------
// FLOAT CONSTANTS
//--------------------------------------------------------------------------
extern const Vect2f  v2fX;
extern const Vect2f  v2fY;
extern const Vect2f  v2fONE;
extern const Vect2f  v2fNEGX;
extern const Vect2f  v2fNEGY;
extern const Vect2f  v2fNEGONE;
extern const Vect2f  v2fZERO;
extern const Vect2f  v2fMAX;
extern const Vect2f  v2fMIN;
extern const Vect2f  v2fFRONT;
extern const Vect2f  v2fRIGHT;
extern const Vect2f  v2fUNIT;

//--------------------------------------------------------------------------
// DOUBLE CONSTANTS
//--------------------------------------------------------------------------
extern const Vect2d  v2dX;
extern const Vect2d  v2dY;
extern const Vect2d  v2dONE;
extern const Vect2d  v2dNEGX;
extern const Vect2d  v2dNEGY;
extern const Vect2d  v2dNEGONE;
extern const Vect2d  v2dZERO;
extern const Vect2d  v2dMAX;
extern const Vect2d  v2dMIN;
extern const Vect2d  v2dTOP;
extern const Vect2d  v2dFRONT;
extern const Vect2d  v2dRIGHT;
extern const Vect2d  v2dUNIT;

//--------------------------------------------------------------------------
// INT CONSTANTS
//--------------------------------------------------------------------------
extern const Vect2i  v2iX;
extern const Vect2i  v2iY;
extern const Vect2i  v2iONE;
extern const Vect2i  v2iNEGX;
extern const Vect2i  v2iNEGY;
extern const Vect2i  v2iNEGONE;
extern const Vect2i  v2iZERO;
extern const Vect2i  v2iTOP;
extern const Vect2i  v2iFRONT;
extern const Vect2i  v2iRIGHT;
extern const Vect2i  v2iUNIT;

#endif //__MATH_VECTOR__VECTOR2__INCLUDED_H__